package com.cci.kangdao.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cci.kangdao.aop.UserThreadLocal;
import com.cci.kangdao.cipapi.CipRespone;
import com.cci.kangdao.cipapi.CipServiceApi;
import com.cci.kangdao.cipapi.VipRequest;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.*;
import com.cci.kangdao.dto.BaseResponse;
import com.cci.kangdao.dto.response.FunctionResponse;
import com.cci.kangdao.service.UserVIPService;
import com.cci.kangdao.utilTool.LocalTimeUtil;
import com.cci.kangdao.utilTool.ParameterTool;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: joe
 * @company: CTY
 * @since: 2024/3/1 14:05
 * @version: V1.0
 **/
@Service
public class UserVIPServiceImpl implements UserVIPService {
    @Resource
    private MemberDao memberDao;
    @Resource
    private CipFleetMapper cipFleetMapper;
    @Resource
    private CustomerEngineRelDao customerEngineRelDao;
    @Resource
    private LoginDao loginDao;
    @Resource
    private AppFunctionCategoryMapper appFunctionCategoryMapper;
    @Resource
    private DictionariesTDao dictionariesTDao;
    @Resource
    private AppFunctionCategoryRecordMapper appFunctionCategoryRecordMapper;
    @Resource
    private VipAttractMapper vipAttractMapper;
    @Resource
    private UserTDao userTDao;
    @Resource
    private CipServiceApi cipServiceApi;
    @Resource
    private UserChannelTMapper userChannelTMapper;

    private static Logger log = Logger.getLogger(UserVIPServiceImpl.class);

    private String REMOVE_FUNTION = "vipRemoveFuntion";

    private String REMOVE_FUNTION_Technician = "RemoveFuntionTechnician";


    /**
     * 获取我的vip 车队，设备，数量
     */
    @Override
    public void getVipData(Map<String, Object> map) {
        UserT userT = UserThreadLocal.get();
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        UserT user = userTDao.selectById(userT.getId());
        Long userId = user.getId();
        //获取车队数量
        List<Map<String, Object>> fleetMapList = cipFleetMapper.getFleetListByUserId(userId, null, 1);
        int fleetCountByUserId = fleetMapList.size();
        //获取设备数量
        int countByUserId = customerEngineRelDao.getCountByUserId(user.getId());
        // 获取vip的数量
        int isVipAndEsnByUserId = memberDao.getIsVipAndEsnByUserId(user.getId(), LocalTimeUtil.getFormatterRealCurrentTime(LocalTimeUtil.DTF_DATE_FORMATTER));
        // 存在待使用的券数量
        VipRequest request = new VipRequest();
        request.setUrl("/gift/giftUnclaimedList");
        Map<String,Object> giftMap = new HashMap<>();
        giftMap.put("giftType",1);
        List<String> channelList = new ArrayList<>();
        channelList.add("1");
        giftMap.put("channelList", channelList);
        String giftUserId = String.valueOf(user.getId());
        Integer channel = 1;
        List<UserChannelT> UserChannelList = userChannelTMapper.getUserChannelListByUserId(userId);
        if(CollectionUtils.isNotEmpty(UserChannelList)){
            channel =  Integer.valueOf(UserChannelList.get(0).getServiceChannel());
            giftUserId = UserChannelList.get(0).getExternalUserId();
        }
        giftMap.put("userId",giftUserId);
        giftMap.put("channel",channel);
        request.setMap(giftMap);
        CipRespone cipRespone = cipServiceApi.getPostDataByCipUrl(request);
        int unclaimedNum = 0;
        if(null != cipRespone && CollectionUtils.isNotEmpty(cipRespone.getDataList())){
            unclaimedNum = cipRespone.getDataList().size();
        }
        int finalUnclaimedNum = unclaimedNum;
        Map<String, Object> mapVo = new HashMap<String, Object>() {{
            put("fleetNum", fleetCountByUserId);
            put("customerEngineRelNum", countByUserId);
            put("vipnNum", isVipAndEsnByUserId);
            put("unclaimedNum", finalUnclaimedNum);
        }};
        ParameterTool.writeSuccessResponse(response, JSON.parseObject(JSON.toJSONString(mapVo)));
    }

    /**
     * 终端用户获取功能项
     */
    @Override
    public void userVipIndex(Map<String, Object> map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        //获取功能项
        UserT userT = UserThreadLocal.get();
        List<FunctionT> functionList = loginDao.getAllFunctionByUserid(userT.getId());
        //查询配置
        List<AppFunctionCategory> list = appFunctionCategoryMapper.getList(1);
        List<FunctionResponse> listVo = this.getFunctionListByCategory(functionList, list,true,REMOVE_FUNTION);
        List<FunctionResponse> tree = this.getTree(listVo);
        tree.sort(Comparator.comparing(FunctionResponse::getSort, Comparator.nullsLast(Integer::compareTo)));
        Map<String, Object> stringObjectMap = new HashMap<>();
        stringObjectMap.put("all", tree);
        //用户是否曾经配置过功能项   道路
        Long appNum = appFunctionCategoryRecordMapper.existFlag(userT.getId(),1);
        List<AppFunctionCategoryRecord> appFunctionCategoryRecords = appFunctionCategoryRecordMapper.selectList(userT.getId(), 1);
        List<FunctionResponse> functionRecordResponseList = this.getFunctionResponseList(tree, appFunctionCategoryRecords);
        if (appNum == 0 && CollectionUtils.isEmpty(functionRecordResponseList)) {
            List<AppFunctionCategory> collect = list.stream().filter(obj -> StringUtils.isNotBlank(obj.getPosition())&&(obj.getPosition().contains("1") || obj.getPosition().contains("3") )).collect(Collectors.toList());
            functionRecordResponseList = this.getFunctionListByCategory(functionList, collect,false,REMOVE_FUNTION);
            functionRecordResponseList = this.getNullTree(tree,functionRecordResponseList);
        }
        //用户是否曾经配置过功能项   非道路
        Long nonAppNum = appFunctionCategoryRecordMapper.existFlag(userT.getId(),2);
        List<AppFunctionCategoryRecord> nonAppFunctionCategoryRecords = appFunctionCategoryRecordMapper.selectList(userT.getId(), 2);
        List<FunctionResponse> nonfunctionRecordResponseList = this.getFunctionResponseList(tree, nonAppFunctionCategoryRecords);
        if (nonAppNum == 0 && CollectionUtils.isEmpty(nonfunctionRecordResponseList)) {
            List<AppFunctionCategory> collect = list.stream().filter(obj -> StringUtils.isNotBlank(obj.getPosition()) && (obj.getPosition().contains("2") || obj.getPosition().contains("3"))).collect(Collectors.toList());
            nonfunctionRecordResponseList = this.getFunctionListByCategory(functionList, collect,false,REMOVE_FUNTION);
            nonfunctionRecordResponseList = this.getNullTree(tree,nonfunctionRecordResponseList);
        }
        stringObjectMap.put("applicationList",functionRecordResponseList );
        stringObjectMap.put("nonApplicationList", nonfunctionRecordResponseList);
        ParameterTool.writeSuccessResponse(response, stringObjectMap);
    }

    private List<FunctionResponse> getNullTree(List<FunctionResponse> tree, List<FunctionResponse> functionResponseList) {
        if (CollectionUtils.isNotEmpty(functionResponseList)&&CollectionUtils.isNotEmpty(tree)) {
            Map<Long, FunctionResponse> appRecordsMap = tree.stream().collect(Collectors.toMap(FunctionResponse::getAppFunctionCategoryId,
                    obj -> obj,
                    (key1, key2) -> key1
            ));
            for (FunctionResponse functionResponse : functionResponseList) {
                if (appRecordsMap.containsKey(functionResponse.getAppFunctionCategoryId())) {
                    FunctionResponse functionResponseVo = appRecordsMap.get(functionResponse.getAppFunctionCategoryId());
                    functionResponse.setSubFunction(functionResponseVo.getSubFunction());
                }
            }
        }
        functionResponseList.sort(Comparator.comparing(FunctionResponse::getSort));
        return functionResponseList;
    }

    public List<FunctionResponse> getFunctionListByCategory(List<FunctionT> functionList,List<AppFunctionCategory> list,boolean showType,String dicStr) {
        Map<Long, AppFunctionCategory> appFunctionCategoryMap = list.stream().collect(Collectors.toMap(AppFunctionCategory::getFunctionId,
                obj -> obj,
                (key1, key2) -> key1
        ));
        List<FunctionResponse> listVo = new ArrayList<>();
        //获取ocr的地址
        String removeFunction = dictionariesTDao.getListByDTableName(dicStr);
        log.error(removeFunction);
        List<Long> emailReminderChannelList = null;
        if (StringUtils.isNotBlank(removeFunction)) {
            emailReminderChannelList = JSON.parseArray(removeFunction, Long.class);
        }
        FunctionResponse functionResponse = null;
        for (FunctionT functionT : functionList) {
            //去除一些无用的数据
            if (CollectionUtils.isNotEmpty(emailReminderChannelList) && emailReminderChannelList.contains(functionT.getId())) {
                continue;
            }
            //去除其他模块的功能项
            if (functionT.getSystemID()!=2) {
                continue;
            }
            functionResponse = new FunctionResponse();
            BeanCopier beanCopier = BeanCopier.create(FunctionT.class, FunctionResponse.class, false);
            beanCopier.copy(functionT, functionResponse, null);
            if (appFunctionCategoryMap.containsKey(functionT.getId())) {
                AppFunctionCategory appFunctionCategory = appFunctionCategoryMap.get(functionT.getId());
                functionResponse.setSegment(appFunctionCategory.getSegment());
                functionResponse.setShowType(appFunctionCategory.getShowType());
                functionResponse.setLabel(appFunctionCategory.getLabel());
                functionResponse.setPosition(appFunctionCategory.getPosition());
                functionResponse.setSort(appFunctionCategory.getSort());
                functionResponse.setfUrl(functionT.getFunUrl());
                functionResponse.setfName(functionT.getFunctionName());
                functionResponse.setNonEsnApplicationLabel(appFunctionCategory.getNonEsnApplicationLabel());
                functionResponse.setAppCustomLabel(appFunctionCategory.getAppCustomLabel());
                functionResponse.setNonAppCustomLabel(appFunctionCategory.getNonAppCustomLabel());
                functionResponse.setCipUrl(appFunctionCategory.getCipUrl());
                functionResponse.setPicUrl(appFunctionCategory.getPicUrl());
                functionResponse.setExperienceFlag(appFunctionCategory.getExperienceFlag());
                functionResponse.setAppFunctionCategoryId(appFunctionCategory.getId());
                if (!showType) {
                    listVo.add(functionResponse);
                }
            }
            if (showType) {
                listVo.add(functionResponse);
            }
        }
        listVo.sort(Comparator.comparing(FunctionResponse::getSort));
        return listVo;
    }
    public List<FunctionResponse> getFunctionResponseList(List<FunctionResponse> tree,List<AppFunctionCategoryRecord> appFunctionCategoryRecords) {
        List<FunctionResponse> listVo = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(appFunctionCategoryRecords) && CollectionUtils.isNotEmpty(tree)) {
            Map<Long, AppFunctionCategoryRecord> appRecordsMap = appFunctionCategoryRecords.stream()
                    .collect(Collectors.toMap(AppFunctionCategoryRecord::getFunctionId,
                    obj -> obj,
                    (key1, key2) -> key1
            ));
            BeanCopier beanCopier = BeanCopier.create(FunctionResponse.class, FunctionResponse.class, false);
            for (FunctionResponse functionResponse : tree) {
                if (appRecordsMap.containsKey(functionResponse.getId())) {
                    FunctionResponse functionResponseVo = new FunctionResponse();
                    beanCopier.copy(functionResponse,functionResponseVo,null);
                    AppFunctionCategoryRecord appFunctionCategoryRecord = appRecordsMap.get(functionResponse.getAppFunctionCategoryId());
                    functionResponseVo.setSort(null == appFunctionCategoryRecord  ? functionResponseVo.getSort(): appFunctionCategoryRecord.getSort());
//                    functionResponseVo.setSubFunction(functionResponse.getSubFunction());
                    listVo.add(functionResponseVo);
                }
            }
        }
        listVo.sort(Comparator.comparing(FunctionResponse::getSort));
        return listVo;
    }

    /**
     * 获取tree结构的数据
     */
    public List<FunctionResponse> getTree(List<FunctionResponse> list) {
        List<FunctionResponse> tree = new ArrayList<>();
        for (Iterator<FunctionResponse> item = list.iterator(); item.hasNext(); ) {
            FunctionResponse node = item.next();
            //如果是根节点
            if (node.getFatherID() == 0) {
                tree.add(node);
                //从所有节点列表中删除该节点，以免后续重复遍历该节点
                item.remove();
            }
        }
        tree.forEach(e -> setChildren(e, list));
        return tree;
    }

    /**
     * 从所有节点列表中查找并设置parent的所有子节点
     *
     * @param parent 父节点
     * @param nodes  所有树节点列表
     */
    public void setChildren(FunctionResponse parent, List<FunctionResponse> nodes) {
        List<FunctionResponse> children = new ArrayList();
        Long parentId = parent.getId();

        for (Iterator<FunctionResponse> iterator = nodes.iterator(); iterator.hasNext(); ) {
            FunctionResponse node = iterator.next();
            if (Objects.equals(node.getFatherID(), parentId)) {
                children.add(node);
                //从所有节点列表中删除该节点，以免后续重复遍历该节点
                iterator.remove();
            }
        }
        //如果孩子为空，则直接返回，否则继续遍历递归设置孩子的孩子
        if (children.isEmpty()) {
            return;
        }
        parent.setSubFunction(children);
        children.forEach(e -> setChildren(e, nodes));
    }

    @Override
    @Transactional
    public BaseResponse saveAppFunctionCategory(String paramStr) {
        UserT userT = UserThreadLocal.get();
        JSONObject jsonObject = JSON.parseObject(paramStr);
        if (null!=jsonObject.get("applicationList")) {
            List<Long> applicationList = JSON.parseArray(JSON.toJSONString(jsonObject.get("applicationList")), Long.class);
            this.saveRecord(userT,1,applicationList);
        }
        if (null!=jsonObject.get("nonApplicationList")) {
            List<Long> nonApplicationList = JSON.parseArray(JSON.toJSONString(jsonObject.get("nonApplicationList")), Long.class);
            this.saveRecord(userT,2,nonApplicationList);
        }
        return BaseResponse.success();
    }

    public void saveRecord(UserT userT,Integer showTyp,List<Long> nonApplicationList){
        appFunctionCategoryRecordMapper.updateAppFunctionCategoryRecord(userT.getId(),showTyp);
        BeanCopier beanCopier = BeanCopier.create(AppFunctionCategory.class, AppFunctionCategoryRecord.class, false);
        if (CollectionUtils.isNotEmpty(nonApplicationList)) {
            AppFunctionCategoryRecord appFunctionCategoryRecord;
            int num = 1;
            for (Long id : nonApplicationList) {
                AppFunctionCategory appFunctionCategory = appFunctionCategoryMapper.selectByFunctionId(id);
                appFunctionCategoryRecord = new AppFunctionCategoryRecord();
                if (null!=appFunctionCategory) {
                    beanCopier.copy(appFunctionCategory, appFunctionCategoryRecord, null);
                    appFunctionCategoryRecord.setAppFunctionCategoryId(appFunctionCategory.getId());
                }
                appFunctionCategoryRecord.setUserId(userT.getId());
                appFunctionCategoryRecord.setCreator(userT.getId());
                appFunctionCategoryRecord.setCreateTime(LocalTimeUtil.getRealCurrentTime());
                appFunctionCategoryRecord.setShowType(showTyp);
                appFunctionCategoryRecord.setFunctionId(id);
                appFunctionCategoryRecord.setSort(num++);
                appFunctionCategoryRecord.setId(null);
                appFunctionCategoryRecord.setFlag(0);
                appFunctionCategoryRecordMapper.insertSelective(appFunctionCategoryRecord);
            }
        }
    }
    @Override
    public BaseResponse getVipAttract() {
        List<VipAttract> vipAttracts = vipAttractMapper.selectList();
        Map<String,Object> mapvo = new HashMap<>();
        if (CollectionUtils.isNotEmpty(vipAttracts)) {
            List<VipAttract> vipParentAttracts = vipAttracts.stream().filter(e -> e.getParentId() == 0).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(vipParentAttracts)) {
                vipAttracts = vipAttracts.stream().filter(e -> e.getParentId() != 0).collect(Collectors.toList());
                for (VipAttract vipAtt : vipParentAttracts) {
                    Map<String, Object> vo = this.getVo(vipAtt.getCategory(), vipAttracts, vipParentAttracts);
                    mapvo.putAll(vo);
                }
            }
        }
        return BaseResponse.success(mapvo);
    }

    public Map<String, Object> getVo(String type, List<VipAttract> vipAttracts, List<VipAttract> vipParentAttracts) {
        Map<String, Object> mapvo = new HashMap<>();
        if (CollectionUtils.isNotEmpty(vipAttracts) && CollectionUtils.isNotEmpty(vipParentAttracts)) {
            for (VipAttract vipAttract : vipParentAttracts) {
                //未充值图  noCar      未充值-道路设备图片配置 noVip  已充值-道路配置图片 vip
                if (type.equals(vipAttract.getCategory())) {
                    Map<String, Object> mapParamvo = new HashMap<>();
                    mapParamvo.put("title", vipAttract.getTitle());
                    List<HashMap<String, Object>> collect = vipAttracts.stream().filter(e -> type.equals(e.getCategory())).sorted(Comparator.comparing(VipAttract::getSort)).map(e -> {
                        return new HashMap<String, Object>() {{
                            put("picUrl", e.getPicUrl());
                            put("url", e.getLinkUrl());
                            put("type", e.getCipFlag());
                            put("application", e.getApplication());
                            put("name", e.getOtherFields());
                        }};
                    }).collect(Collectors.toList());
                    mapParamvo.put("pics", collect);
                    mapvo.put(type, mapParamvo);
                }
            }
        }
        return mapvo;
    }
    /**
     * b端用户获取车联网功能项
     * @param map
     */
    @Override
    public void userNetworkVipIndex(Map<String, Object> map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        //获取功能项
        UserT userT = UserThreadLocal.get();
        Map<String, Object> stringObjectMap = new HashMap<>();
        //查询配置
        List<AppFunctionCategory> list = appFunctionCategoryMapper.getList(2);
        if (CollectionUtils.isEmpty(list)) {
            stringObjectMap.put("applicationList",new ArrayList<>());
            stringObjectMap.put("nonApplicationList", new ArrayList<>());
            ParameterTool.writeSuccessResponse(response, stringObjectMap);
        }
        List<Long> paraFunction = list.stream().map(AppFunctionCategory::getFunctionId).collect(Collectors.toList());
        List<FunctionT> functionList = loginDao.getAllFunctionByList(paraFunction);
        List<FunctionResponse> listVo = this.getFunctionListByCategory(functionList, list,false,REMOVE_FUNTION_Technician);
        List<FunctionResponse> tree = this.getTree(listVo);
        tree.sort(Comparator.comparing(FunctionResponse::getSort, Comparator.nullsLast(Integer::compareTo)));

        stringObjectMap.put("all", tree);
        //用户是否曾经配置过功能项   道路
        Long appNum = appFunctionCategoryRecordMapper.existFlag(userT.getId(),1);
        List<AppFunctionCategoryRecord> appFunctionCategoryRecords = appFunctionCategoryRecordMapper.selectList(userT.getId(), 1);
        List<FunctionResponse> functionRecordResponseList = this.getFunctionResponseList(tree, appFunctionCategoryRecords);
        if (appNum == 0 && CollectionUtils.isEmpty(functionRecordResponseList)) {
            List<AppFunctionCategory> collect = list.stream().filter(obj -> StringUtils.isNotBlank(obj.getPosition())&&(obj.getPosition().contains("1") || obj.getPosition().contains("3") )).collect(Collectors.toList());
            functionRecordResponseList = this.getFunctionListByCategory(functionList, collect,false,REMOVE_FUNTION_Technician);
            functionRecordResponseList = this.getNullTree(tree,functionRecordResponseList);
        }
        //用户是否曾经配置过功能项   非道路
        Long nonAppNum = appFunctionCategoryRecordMapper.existFlag(userT.getId(),2);
        List<AppFunctionCategoryRecord> nonAppFunctionCategoryRecords = appFunctionCategoryRecordMapper.selectList(userT.getId(), 2);
        List<FunctionResponse> nonfunctionRecordResponseList = this.getFunctionResponseList(tree, nonAppFunctionCategoryRecords);
        if (nonAppNum == 0 && CollectionUtils.isEmpty(nonfunctionRecordResponseList)) {
            List<AppFunctionCategory> collect = list.stream().filter(obj -> StringUtils.isNotBlank(obj.getPosition()) && (obj.getPosition().contains("2") || obj.getPosition().contains("3"))).collect(Collectors.toList());
            nonfunctionRecordResponseList = this.getFunctionListByCategory(functionList, collect,false,REMOVE_FUNTION_Technician);
            nonfunctionRecordResponseList = this.getNullTree(tree,nonfunctionRecordResponseList);
        }
        stringObjectMap.put("applicationList",functionRecordResponseList );
        stringObjectMap.put("nonApplicationList", nonfunctionRecordResponseList);
        ParameterTool.writeSuccessResponse(response, stringObjectMap);
    }
}
